Asynchronous Semaphore is a structure that is being used in asynchronous programming models. It's goal is to lock an action to run only after other asynchronous actions have been executed.
It got the name semaphore since it's a specific use of the abstract structure semaphore in the world of asynchronous programming.
The semaphore concept was invented by Dutch computer scientist Edsger Dijkstra, the name "Asynchronous Semaphore" and the specific usage in the asynchronous world was coined by Ohad Assulin, a computer scientist for the Hebrew University of Jerusalem.
Upon creation, asynchronous semaphore receives a function as an argument, this argument is usually called the "fire-function". The fire-function will get executed after the asynchronous actions will be done.
Whereas the programmer calls asynchronous action (that will get invoke later on sometimes), the programmer also calls the async semaphore's v() function in order to increase the internal semaphore lock variable which represents the fact that this asynchronous action has been add to the queue and will run later sometimes. Whereas the callback of that asynchronous function is done running, the programmer calls the p() function which decreases the internal lock variable. (this represents the fact that the asynchronous action is done)
The p() function also checks if the lock variable equals to 0, if it does, it means that all the async actions have been done running hence the "fire-function" is allowed to get invoked.
Asynchronous semaphore is efficient when the asynchronous actions are independent.
Async Semaphore(JavaScript):
function asem(fireFunc,initLock){ if(initLock) this.lock=initLock; else this.lock=0; this.func = fireFunc; } asem.prototype.v = function(){ this.lock++; } asem.prototype.p = function(){ this.lock--; if(this.lock==0 && this.func) this.func(); }
In order to enable the programmer to call v() and p() easily, sometimes the asem includes a wrapping functionality
asem.prototype.wrap = function(func){ var self = this; self.v(); return function(){ if(func) func.apply(this,arguments); self.p(); } }
Example(JavaScript on top of node.js):
One would like to read data from two files, manipulate the data and write it to another file
var data1; var data2; function write(){ var data = manipulate(data1,data2) fs.writeFile('f', data, function (err) { if (err) throw err; console.log('It\'s saved!'); }); }; var lockReads = new asem(write); lockReads.v(); fs.readFile('f1', function (err, data) { if (err) throw err; data1 = d1manipulation(data); lockReads.p(); }); lockReads.v(); fs.readFile('f2', function (err, data) { if (err) throw err; data2 = d2manipulation(data); lockReads.p(); }); //... //...